////
/// @group list
////

@use "sass:map";
@use "../utils";
@use "../spacing";
@use "../theme/theme";
@use "../avatar/avatar";
@use "../icon/icon";
@use "../divider/divider";
@use "../interaction/interaction";
@use "../typography/typography";

/// Set to `true` to disable all the styles.
/// @type Boolean
$disable-everything: false !default;

/// Set to `true` to disable the horizontal list styles.
/// @type Boolean
$disable-horizontal: false !default;

/// Set to `true` to disable the dense list styles
/// @type Boolean
$disable-dense: false !default;

/// Set to `true` if the `ListItem` will always enable the `disabledOpacity`
/// prop.
/// @see $disable-item-disabled-opacity
/// @type Boolean
$disable-item-disabled-color: false !default;

/// Set to `true` if the `ListItem` will never enable the `disabledOpacity`
/// prop.
/// @type Boolean
$disable-item-disabled-opacity: false !default;

/// Set to `true` if the `ListItem` will never use an `Avatar` as an addon.
///
/// @type Boolean
$disable-item-avatar: false;

/// Set to `true` if the `ListItem` will never use a media addon.
///
/// @type Boolean
$disable-item-media: false !default;

/// Set to `true` if the `ListItem` will never use a large media addon.
///
/// @type Boolean
$disable-item-media-large: false !default;

/// Set to `true` if the `ListItem` will never use `height="medium"`or an icon
/// addon.
/// @type Boolean
$disable-medium-height: false !default;

/// Set to `true` if the `ListItem` will never use `height="large"`or an avatar
/// addon.
/// @type Boolean
$disable-large-height: false !default;

/// Set to `true` if the `ListItem` will never use `height="extra-large"`,
/// secondary text or a media addon.
///
/// @type Boolean
$disable-extra-large-height: false !default;

/// Set to `true` if the `ListItem` will never enable the `multiline` prop for
/// `secondaryText`.
/// @type Boolean
$disable-multiline-clamp: false !default;

/// Set to `true` if the `ListItem` will never enable the `multiline` prop for
/// `secondaryText`.
/// @type Boolean
$disable-multiline-height: true !default;

/// Set to `true` if the `ListItemLink` component will not be used.
/// @type Boolean
$disable-item-link-styles: false !default;

/// Set to `true` if the `ListSubheader` component will not be used.
/// @type Boolean
$disable-subheader: false !default;

/// Set to `true` if the `inset` prop will never be enabled on the
/// `ListSubheader` component.
/// @type Boolean
$disable-subheader-inset: false !default;

/// Set to `true` if a `Divider` will never enable the `inset` prop within a
/// `List`.
/// @type Boolean
$disable-divider-inset: divider.$disable-everything !default;

/// The vertical padding to apply to the `List` component.
/// @type Number
$vertical-padding: spacing.get-var(sm) !default;

/// The vertical padding to apply to a dense `List` component.
/// @type Number
$dense-vertical-padding: spacing.get-var(xs) !default;

/// The horizontal padding to apply to the `List` component.
/// @type Number
$horizontal-padding: spacing.get-var(none) !default;

/// The horizontal padding to apply to a dense `List` component.
/// @type Number
$dense-horizontal-padding: $horizontal-padding !default;

/// The default font-size to apply to a dense `List` component. This will be
/// applied after the `$typography-styles`.
///
/// @see $typography-styles
/// @type Number
$dense-font-size: 0.8125rem !default;

/// The default typography to apply to the `List` component.
/// @type Map
$typography-styles: map.merge(
  typography.$subtitle-1-styles,
  (
    line-height: map.get(typography.$body-1-styles, line-height),
  )
) !default;

/// The amount of opacity to apply to a disabled `ListItem` and the
/// `disableOpacity` prop has been enabled.
///
/// @type Number
$item-disabled-opacity: 0.5 !default;

/// The vertical padding to apply to `ListItem`.
/// @type Number
$item-vertical-padding: spacing.get-var(sm) !default;

/// The horizontal padding to apply to `ListItem`.
/// @type Number
$item-horizontal-padding: spacing.get-var(md) !default;

/// The default height for a `ListItem` that has no addons or secondary text.
/// @type Number
$item-height: 3rem !default;

/// The default height for a dense `ListItem` that has no addons or secondary
/// text.
/// @type Number
$item-dense-height: 2.5rem !default;

/// The default height for a `ListItem` that set `height="medium"` or has an
/// icon addon with no secondary text.
///
/// @type Number
$item-medium-height: 3.5rem !default;

/// The default height for a dense `ListItem` that set `height="medium"` or has
/// an icon addon with no secondary text.
///
/// @type Number
$item-dense-medium-height: 3rem !default;

/// The default height for a `ListItem` that set `height="large"` or has an
/// avatar addon with no secondary text.
///
/// @type Number
$item-large-height: 4rem !default;

/// The default height for a dense `ListItem` that set `height="large"` or has
/// an avatar addon with no secondary text.
///
/// @type Number
$item-dense-large-height: 3.5rem !default;

/// The default height for a `ListItem` that set `height="extra-large"` or has
/// secondary text or a media addon
///
/// @type Number
$item-extra-large-height: 4.5rem !default;

/// The default height for a dense `ListItem` that set `height="extra-large"`
/// or has secondary text or a media addon
///
/// @type Number
$item-dense-extra-large-height: 4rem !default;

/// The default `line-clamp` for a `ListItem` when the `multiline` prop is
/// enabled and `secondaryText` was provided.
///
/// @type Number
$item-multiline-clamp: 2 !default;

/// The default height for a `ListItem` that has the `multiline` prop enabled.
/// @type Number
$item-multiline-height: 5.5rem !default;

/// The default height for a `ListItem` that has the `multiline` and `dense`
/// props enabled.
///
/// @type Number
$item-dense-multiline-height: 5rem !default;

/// The amount of spacing between a media addon and the `ListItem` content.
///
/// @type Number
$item-media-spacing: spacing.get-var(md) !default;

/// The default size for a media addon in the `ListItem` component.
///
/// @type Number
$item-media-size: 3.5rem !default;

/// The default size for a large media addon in the `ListItem` component.
///
/// @type Number
$item-media-large-size: 6.25rem !default;

/// The `line-height` to apply to the secondary text within a `ListItem`.
/// @type Number
$item-secondary-text-line-height: 1.42857 !default;

/// The `max-height` to apply to the `ListItem` secondary text which enables
/// the line-clamp behavior.
///
/// @type Number
$item-secondary-text-multiline-max-height: 3rem !default;

/// The default keyline to apply to text content in a `ListItem` when an icon
/// or `Avatar` are provided as addons. In other words, the text will be this
/// distance from the left of the `ListItem`.
///
/// This will also be the `Divider` inset distance.
///
/// @type Number
$item-keyline: 4.5rem !default;

/// The default keyline to apply when the `List` has dense mode enabled.
///
/// @type Number
$item-dense-keyline: 3.5rem !default;

/// The available configurable css variables and mostly used internally for the
/// `get-var`, `set-var`, and `use-var` utils.
/// @type List
$variables: (
  horizontal-padding,
  vertical-padding,
  item-keyline,
  item-horizontal-padding,
  item-vertical-padding,
  item-height,
  item-medium-height,
  item-large-height,
  item-extra-large-height,
  item-multiline-height,
  item-media-size,
  item-media-spacing,
  item-text-multiline-height,
  item-multiline-clamp
);

/// @param {String} name - The supported variable name
/// @param {any} fallback [null] - An optional fallback value
/// @returns {String} a `var()` statement
@function get-var($name, $fallback: null) {
  $var: utils.get-var-name($variables, $name, "list");
  @if $fallback {
    @return var(#{$var}, #{$fallback});
  }

  @return var(#{$var});
}

/// @param {String} name - The supported variable name
/// @param {any} value - The value to set the variable to. Supports `null` which
/// will just be a no-op.
@mixin set-var($name, $value) {
  @if $value {
    #{utils.get-var-name($variables, $name, "list")}: #{$value};
  }
}

/// @param {String} property - The css property to apply the variable to
/// @param {String} name [$property] - The supported variable name
/// @param {any} fallback [null] - An optional fallback value if the variable
/// has not been set
@mixin use-var($property, $name: $property, $fallback: null) {
  #{$property}: get-var($name, $fallback);
}

/// Sets the icon spacing variable with additional spacing.
/// @access private
/// @param {String|Number} $subtract - The additional icon spacing to subtract
/// in the `calc` expression.
@mixin _addon-spacing($subtract) {
  $keyline: get-var(item-keyline);
  $padding: get-var(item-horizontal-padding);

  @include icon.set-var(
    spacing,
    calc(#{$keyline} - #{$padding} - #{$subtract})
  );
}

/// Conditionally applies the css variables based on feature flags
@mixin variables {
  @if not $disable-everything {
    @include set-var(horizontal-padding, $horizontal-padding);
    @include set-var(vertical-padding, $vertical-padding);
    @include set-var(item-horizontal-padding, $item-horizontal-padding);
    @include set-var(item-vertical-padding, $item-vertical-padding);
    @include set-var(item-keyline, $item-keyline);

    @include set-var(item-height, $item-height);
    @if not $disable-medium-height {
      @include set-var(item-medium-height, $item-medium-height);
    }
    @if not $disable-large-height {
      @include set-var(item-large-height, $item-large-height);
    }
    @if not $disable-extra-large-height {
      @include set-var(item-extra-large-height, $item-extra-large-height);
    }
    @if not $disable-multiline-clamp {
      @include set-var(item-multiline-clamp, $item-multiline-clamp);
    }
    @if not $disable-multiline-height {
      @include set-var(item-multiline-height, $item-multiline-height);
      @include set-var(
        item-text-multiline-height,
        $item-secondary-text-multiline-max-height
      );
    }

    @if not $disable-item-media {
      @include set-var(item-media-size, $item-media-size);
      @include set-var(item-media-spacing, $item-media-spacing);
    }
  }
}

/// Generates all the styles based on feature flags.
///
/// @param {Boolean} disable-layer [false] - Set this to `true` to disable the
/// layer behavior
@mixin styles($disable-layer: false) {
  @if not $disable-everything {
    @include utils.optional-layer(list, $disable-layer) {
      .rmd-list {
        @include utils.map-to-styles($typography-styles);
        @if not $disable-divider-inset {
          @include divider.set-var(inset, get-var(item-keyline));
        }

        list-style: none;
        margin: 0;
        padding: get-var(vertical-padding) get-var(horizontal-padding);

        @if not $disable-horizontal {
          &--horizontal {
            display: flex;
            flex-wrap: nowrap;
            max-width: 100%;
            overflow: auto;
            padding: get-var(horizontal-padding) get-var(vertical-padding);
          }
        }

        @if not $disable-dense {
          &--dense {
            @include icon.set-var(size, icon.get-var(dense-size));
            @include set-var(vertical-padding, $dense-vertical-padding);
            @include set-var(horizontal-padding, $dense-horizontal-padding);
            @include set-var(item-height, $item-dense-height);
            @include set-var(item-medium-height, $item-dense-medium-height);
            @include set-var(item-large-height, $item-dense-large-height);
            @include set-var(
              item-extra-large-height,
              $item-dense-extra-large-height
            );
            @include set-var(
              item-text-multiline-height,
              $item-dense-multiline-height
            );
            @include set-var(item-keyline, $item-dense-keyline);

            font-size: $dense-font-size;
          }
        }
      }

      .rmd-list-item {
        @include use-var(min-height, item-height);

        align-items: center;
        display: flex;
        padding: get-var(item-vertical-padding) get-var(item-horizontal-padding);

        &--clickable {
          @include interaction.surface(
            $disabled-selector: '&[aria-disabled="true"]'
          );
        }

        @if not $disable-item-link-styles {
          &--link {
            color: inherit;
            text-decoration: none;
          }
        }

        @if not $disable-item-disabled-color {
          &--disabled-color {
            @include theme.theme-set-var(
              text-secondary-color,
              theme.theme-get-var(text-disabled-color)
            );
            @include theme.theme-use-var(color, text-disabled-color);
          }
        }

        @if not $disable-item-disabled-opacity {
          &--disabled-opacity {
            opacity: $item-disabled-opacity;
          }
        }

        @if not $disable-medium-height {
          &--medium {
            @include set-var(item-height, get-var(item-medium-height));
          }
        }

        @if not $disable-large-height {
          &--large {
            @include set-var(item-height, get-var(item-large-height));
          }
        }

        @if not $disable-extra-large-height {
          &--extra-large {
            @include set-var(item-height, get-var(item-extra-large-height));
          }
        }

        @if not $disable-multiline-height {
          &--multiline {
            @include set-var(item-height, get-var(item-multiline-height));
          }
        }

        &__text {
          @include typography.text-overflow;

          display: block;
          flex-grow: 1;

          &--secondary {
            @include theme.theme-use-var(color, text-secondary-color);
          }

          @if not $disable-multiline-clamp {
            &--clamped {
              @include typography.line-clamp(get-var(item-multiline-clamp));
              @if not $disable-multiline-height {
                @include use-var(max-height, item-text-multiline-height);
              }

              line-height: $item-secondary-text-line-height;
              white-space: normal;
            }
          }

          @include utils.rtl {
            margin-left: auto;
          }
        }

        &__addon {
          flex-shrink: 0;

          &--top {
            align-self: flex-start;
          }

          &--bottom {
            align-self: flex-end;
          }

          &--before {
            @include _addon-spacing(icon.get-var(size));
          }

          @if not $disable-item-avatar {
            &--avatar-before {
              @include _addon-spacing(avatar.get-var(size));
            }
          }

          @if not $disable-item-media {
            &--media {
              @include icon.set-var(spacing, get-var(item-media-spacing));
              @include use-var(width, item-media-size);
            }

            &--media-centered {
              align-items: center;
              display: flex;
              justify-content: center;
            }

            @if not $disable-item-media-large {
              &--media-large {
                @include set-var(item-media-size, $item-media-large-size);
              }
            }
          }
        }
      }

      @if not $disable-subheader {
        .rmd-list-subheader {
          @include utils.map-to-styles(typography.$subtitle-2-styles);
          @include theme.theme-use-var(color, text-secondary-color);
          @include use-var(height, item-height);

          align-items: center;
          display: flex;
          padding: get-var(item-vertical-padding)
            get-var(item-horizontal-padding);

          @if not $disable-subheader-inset {
            &--inset {
              @include use-var(padding-left, item-keyline);

              @include utils.rtl {
                @include use-var(padding-left, item-horizontal-padding);
                @include use-var(padding-right, item-keyline);
              }
            }
          }
        }
      }
    }
  }
}
